/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package gride.plugin.projectbrowser;

import gride.project.GrideLibrary;
import gride.project.GrideScript;
import gride.project.Project;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import javax.swing.tree.TreeNode;



/**
 *
 * @author lukasz
 */
public class ProjectTreeNode implements TreeNode
{
    /**
     *
     */
    public static final int PROJECT = 0;
    /**
     *
     */
    public static final int SCRIPTS = 1;
    /**
     *
     */
    public static final int SCRIPT_PACKAGE = 2;
    /**
     *
     */
    public static final int SCRIPT = 3;
    /**
     *
     */
    public static final int LIBRARIES = 7;
    /**
     *
     */
    public static final int LIBRARY = 8;

    private int type;
    private TreeNode parent;
    private Object object;

    /**
     *
     * @param type
     * @param parent
     * @param object
     */
    public ProjectTreeNode(int type, TreeNode parent, Object object)
    {
        this.type = type;
        this.parent = parent;
        this.object = object;
    }

    public TreeNode getChildAt(int childIndex)
    {
        switch(type)
        {
            case PROJECT:
                switch(childIndex)
                {
                    case 0:
                        return new ProjectTreeNode(SCRIPTS, this, object);

                    case 1:
                        return new ProjectTreeNode(LIBRARIES, this, object);
                }

            case SCRIPTS:
                Object[] spObject = { object,
                     ((Project)object).getScriptPackageList().get(childIndex) };
                return new ProjectTreeNode(SCRIPT_PACKAGE, this, spObject);

            case SCRIPT_PACKAGE:
                Project spProject = (Project) ((Object[])object)[0];
                String spPkg = (String) ((Object[])object)[1];
                return new ProjectTreeNode(SCRIPT, this,
                          spProject.getScriptsInPackage(spPkg).get(childIndex));

            case LIBRARIES:
                GrideLibrary l =
                               ((Project)object).getLibraries().get(childIndex);
                return new ProjectTreeNode(LIBRARY, this, l);

            default:
                return null;
        }
    }

    public int getChildCount()
    {
        switch (type)
        {
            case PROJECT:
                return 2;

            case SCRIPTS:
                return ((Project)object).getScriptPackageList().size();

            case SCRIPT_PACKAGE:
                Project spProject = (Project) ((Object[])object)[0];
                String spPkg = (String) ((Object[])object)[1];
                return spProject.getScriptsInPackage(spPkg).size();

            case LIBRARIES:
                return ((Project)object).getLibraries().size();

            default:
                return 0;
        }
    }

    public TreeNode getParent()
    {
        return parent;
    }

    public int getIndex(TreeNode node)
    {
        switch(type)
        {
            case PROJECT:
                switch(((ProjectTreeNode)node).getType())
                {
                    case SCRIPTS:
                        return 0;

                    case LIBRARIES:
                        return 1;

                    default:
                        return -1;
                }

            case SCRIPTS:
                if (((ProjectTreeNode)node).getType() == SCRIPT_PACKAGE)
                {
                    String spPkg = (String)
                             ((Object[])((ProjectTreeNode)node).getObject())[1];
                    List<String> spList =
                             ((Project)object).getScriptPackageList();
                    for (int i=0; i<spList.size(); i++)
                        if (spList.get(i).equals(spPkg))
                            return i;
                }
                else
                    return -1;

            case SCRIPT_PACKAGE:
                if (((ProjectTreeNode)node).getType() == SCRIPT)
                {
                    Project spProject = (Project) ((Object[])object)[0];
                    String spPackage = (String) ((Object[])object)[1];
                    GrideScript s = (GrideScript)
                                            ((ProjectTreeNode)node).getObject();
                    for (int i=0;
                         i<spProject.getScriptsInPackage(spPackage).size(); i++)
                        if (spProject.getScriptsInPackage(spPackage).get(i).
                            getName().equals(s.getName()))
                            return i;
                }
                else
                    return -1;

            case LIBRARIES:
                if (((ProjectTreeNode)node).getType() == LIBRARY)
                {
                    GrideLibrary s = (GrideLibrary)
                                            ((ProjectTreeNode)node).getObject();
                    for (int i=0; i<((Project)object).getLibraries().size();
                         i++)
                        if (((Project)object).getLibraries().get(i).
                            getName().equals(s.getName()))
                            return i;
                }
                else
                    return -1;

            default:
                return -1;

        }
    }

    public boolean getAllowsChildren()
    {
        switch(type)
        {
            case PROJECT:
            case SCRIPTS:
            case SCRIPT_PACKAGE:
            case LIBRARIES:
                return true;

            default:
                return false;
        }
    }

    public boolean isLeaf()
    {
        switch(type)
        {
            case PROJECT:
            case SCRIPTS:
            case SCRIPT_PACKAGE:
            case LIBRARIES:
                return false;

            default:
                return true;
        }
    }

    public Enumeration children()
    {
        ArrayList<TreeNode> children = new ArrayList<TreeNode>();

        switch(type)
        {
            case PROJECT:
                children.add(new ProjectTreeNode(SCRIPTS, this, object));
                children.add(new ProjectTreeNode(LIBRARIES, this, object));

            case SCRIPTS:
                for (String p : ((Project)object).getScriptPackageList())
                {
                    Object[] spObject = { object, p };
                    children.add(new ProjectTreeNode(SCRIPT_PACKAGE, this,
                                                     spObject));
                }

            case SCRIPT_PACKAGE:
                Project spProject = (Project) ((Object[])object)[0];
                String spPackage = (String) ((Object[])object)[1];
                for (GrideScript s : spProject.getScriptsInPackage(spPackage))
                    children.add(new ProjectTreeNode(SCRIPT, this, s));

            case LIBRARIES:
                for (GrideLibrary s : ((Project)object).getLibraries())
                    children.add(new ProjectTreeNode(LIBRARY, this, s));
        }

        return new TreeNodeArrayEnumeration(children);
    }


    @Override
    public String toString()
    {
        switch (type)
        {
            case PROJECT:
                return ((Project)object).getName();

            case SCRIPTS:
                return "Scripts";

            case SCRIPT_PACKAGE:
                String spPackage = (String) ((Object[])object)[1];
                if (spPackage.equals(""))
                    return "<default>";
                else
                    return spPackage;

            case SCRIPT:
                GrideScript script = (GrideScript) object;
                if (script.isMainScript())
                    return script.getName() + " (MAIN)";
                else
                    return script.getName();

            case LIBRARIES:
                return "Libraries";

            case LIBRARY:
                return ((GrideLibrary)object).getName();

            default:
                return object.toString();
        }
    }

    /**
     * 
     * @return
     */
    public int getType()
    {
        return type;
    }

    /**
     *
     * @return
     */
    public Object getObject()
    {
        return object;
    }


}


class TreeNodeArrayEnumeration implements Enumeration
{
    ArrayList<TreeNode> children = new ArrayList<TreeNode>();
    int currentIndex;

    public TreeNodeArrayEnumeration(ArrayList<TreeNode> children)
    {
        this.children = children;
        currentIndex = 0;
    }

    public boolean hasMoreElements()
    {
        return currentIndex < children.size();
    }

    public Object nextElement() {
        return children.get(currentIndex++);
    }
}



